package cryptography.signature;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;

public class SignatureDSASUN {

	public static void main(String[] args) throws Exception {

		/* Generate a DSA signature */

		// the rest of the code goes here

		sign("This is a signature", "sig", "pub");

		verify("This is a signature",
				"D:/Data/Eclipse Projects/JavaMailClient/signatures/sig",
				"D:/Data/Eclipse Projects/JavaMailClient/signatures/pub");
	}

	public static void sign(String data, String sigFilename,
			String publicFilename) throws Exception {

		KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");

		SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
		keyGen.initialize(1024, random);

		KeyPair pair = keyGen.generateKeyPair();
		PrivateKey priv = pair.getPrivate();
		PublicKey pub = pair.getPublic();

		Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");

		dsa.initSign(priv);

		byte[] buffer = data.getBytes("utf-8");
		dsa.update(buffer, 0, buffer.length);

		byte[] realSig = dsa.sign();

		/* save the signature in a file */
		FileOutputStream sigfos = new FileOutputStream("signatures/"
				+ sigFilename);
		sigfos.write(realSig);
		sigfos.close();

		/* save the public key in a file */
		byte[] key = pub.getEncoded();
		FileOutputStream keyfos = new FileOutputStream("signatures/"
				+ publicFilename);
		keyfos.write(key);
		keyfos.close();
	}

	public static void signFile(String dataFilename, String sigFilename,
			String publicFilename) throws Exception {

		KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");

		SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
		keyGen.initialize(1024, random);

		KeyPair pair = keyGen.generateKeyPair();
		PrivateKey priv = pair.getPrivate();
		PublicKey pub = pair.getPublic();

		Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");

		dsa.initSign(priv);

		FileInputStream fis = new FileInputStream(dataFilename);
		BufferedInputStream bufin = new BufferedInputStream(fis);
		byte[] buffer = new byte[1024];
		int len;
		while ((len = bufin.read(buffer)) >= 0) {
			dsa.update(buffer, 0, len);
		}
		;
		bufin.close();

		byte[] realSig = dsa.sign();

		/* save the signature in a file */
		FileOutputStream sigfos = new FileOutputStream("signatures/"
				+ sigFilename);
		sigfos.write(realSig);
		sigfos.close();

		/* save the public key in a file */
		byte[] key = pub.getEncoded();
		FileOutputStream keyfos = new FileOutputStream("signatures/"
				+ publicFilename);
		keyfos.write(key);
		keyfos.close();
	}

	public static boolean verify(String data, String sigFilename,
			String publicFilename) throws Exception {

		FileInputStream keyfis = new FileInputStream(publicFilename);
		byte[] encKey = new byte[keyfis.available()];
		keyfis.read(encKey);

		keyfis.close();

		X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);

		KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");

		PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);

		FileInputStream sigfis = new FileInputStream(sigFilename);
		byte[] sigToVerify = new byte[sigfis.available()];
		sigfis.read(sigToVerify);
		sigfis.close();

		Signature sig = Signature.getInstance("SHA1withDSA", "SUN");

		sig.initVerify(pubKey);

		byte[] buffer = data.getBytes("utf-8");
		sig.update(buffer, 0, buffer.length);

		boolean verifies = sig.verify(sigToVerify);

		return verifies;
	}

	public static boolean verifyFile(String dataFilename, String sigFilename,
			String publicFilename) throws Exception {

		FileInputStream keyfis = new FileInputStream(publicFilename);
		byte[] encKey = new byte[keyfis.available()];
		keyfis.read(encKey);

		keyfis.close();

		X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);

		KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");

		PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);

		FileInputStream sigfis = new FileInputStream(sigFilename);
		byte[] sigToVerify = new byte[sigfis.available()];
		sigfis.read(sigToVerify);
		sigfis.close();

		Signature sig = Signature.getInstance("SHA1withDSA", "SUN");

		sig.initVerify(pubKey);

		FileInputStream datafis = new FileInputStream(dataFilename);
		BufferedInputStream bufin = new BufferedInputStream(datafis);

		byte[] buffer = new byte[1024];
		int len;
		while (bufin.available() != 0) {
			len = bufin.read(buffer);
			sig.update(buffer, 0, len);
		}
		;

		boolean verifies = sig.verify(sigToVerify);

		return verifies;
	}
}
